import os
import struct
import hashlib
from typing import Dict, Optional, List
from dataclasses import dataclass

@dataclass
class FileInfo:
    """文件信息类"""
    name: str
    offset: int
    size: int
    checksum: str

class ResourceReader:
    """资源读取器"""
    MAGIC = 0x44545753
    
    def __init__(self, bin_file: str):
        """初始化资源读取器"""
        self.bin_file = bin_file
        self.files: Dict[str, FileInfo] = {}
        self._load_index()
    
    def _calculate_checksum(self, data: bytes) -> str:
        """计算数据的校验和"""
        return hashlib.sha256(data).hexdigest()
    
    def _load_index(self):
        """加载文件索引"""
        with open(self.bin_file, 'rb') as f:
            # 读取文件头
            magic = struct.unpack('<I', f.read(4))[0]
            if magic != self.MAGIC:
                raise ValueError("无效的资源文件")
            
            # 读取版本和文件数量
            version = struct.unpack('<I', f.read(4))[0]
            file_count = struct.unpack('<I', f.read(4))[0]
            
            # 读取文件校验和
            file_checksum = f.read(32).hex()
            
            # 验证文件完整性
            checksum_pos = f.tell()
            f.seek(12)  # 跳过魔数、版本号、文件数量
            data_for_checksum = f.read()
            if self._calculate_checksum(data_for_checksum) != file_checksum:
                raise ValueError("资源文件已被修改")
            
            # 读取文件索引
            f.seek(checksum_pos)
            for _ in range(file_count):
                # 读取文件名
                name_len = struct.unpack('<I', f.read(4))[0]
                name = f.read(name_len).decode('utf-8')
                
                # 读取文件信息
                offset = struct.unpack('<Q', f.read(8))[0]
                size = struct.unpack('<Q', f.read(8))[0]
                checksum = f.read(32).hex()
                
                # 保存文件信息
                self.files[name] = FileInfo(name, offset, size, checksum)
    
    def read_file(self, filename: str) -> Optional[bytes]:
        """读取文件内容"""
        if filename not in self.files:
            return None
        
        file_info = self.files[filename]
        with open(self.bin_file, 'rb') as f:
            f.seek(file_info.offset)
            data = f.read(file_info.size)
            
            # 验证文件完整性
            if self._calculate_checksum(data) != file_info.checksum:
                raise ValueError(f"文件已被修改: {filename}")
            
            return data
    
    def list_files(self) -> List[str]:
        """列出所有文件"""
        return list(self.files.keys())
    
    @staticmethod
    def read_qss(path: str) -> str:
        """读取QSS样式文件"""
        try:
            with open(path, "r", encoding="utf-8") as f:
                return f.read()
        except Exception as e:
            print(f"Error reading QSS file: {e}")
            return ""